package com.example.demo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.dto.BoardroomAddDTO;
import com.example.demo.dto.BoardroomStatusDTO;
import com.example.demo.dto.BoardroomUpdateDTO;
import com.example.demo.dto.DeviceDTO;
import com.example.demo.mapper.*;
import com.example.demo.pojo.Boardroom;
import com.example.demo.pojo.BoardroomState;
import com.example.demo.pojo.Device;
import com.example.demo.pojo.Orders;
import com.example.demo.service.BoardroomService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.service.BoardroomStateService;
import com.example.demo.service.DeviceService;
import com.example.demo.utils.DateUtils;
import com.example.demo.vo.BoardroomDevVO;
import org.junit.platform.commons.util.StringUtils;
import com.example.demo.vo.ResultVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author sjy
 * @since 2025-05-25
 */
@Service
public class BoardroomServiceImpl extends ServiceImpl<BoardroomMapper, Boardroom> implements BoardroomService {
    private final BoardroomMapper boardroomMapper;
    private final DeviceService deviceService;
    private final BoardroomStateMapper boardroomStateMapper;

    @Autowired
    private CustomerMapper customerMapper;
    @Autowired
    private OrdersMapper ordersMapper;


    // 使用构造函数注入
    public BoardroomServiceImpl(BoardroomMapper boardroomMapper, DeviceService deviceService, DeviceMapper deviceMapper, BoardroomStateMapper boardroomStateMapper) {
        this.boardroomMapper = boardroomMapper;
        this.deviceService = deviceService;
        this.boardroomStateMapper = boardroomStateMapper;
    }

    private boolean hasFutureReservations(Integer boardroomId) {
        LocalDate today = LocalDate.now();
        LocalTime now = LocalTime.now();

        QueryWrapper<BoardroomState> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("boardroom_id", boardroomId)
                .in("state", Arrays.asList(2, 3, 5))
                .and(wrapper -> wrapper
                        .gt("date", today)
                        .or()
                        .eq("date", today)
                        .gt("end_time", now)
                );
        return boardroomStateMapper.selectCount(queryWrapper) > 0;
    }

    @Override
    public IPage<BoardroomDevVO> queryBoardroomsWithDevices(Integer id, String name, Integer pageNo, Integer pageSize) {
        Page<Boardroom> page = new Page<>(pageNo, pageSize);
        QueryWrapper<Boardroom> queryWrapper = new QueryWrapper<>();
        if(id != null){
            queryWrapper.eq("id",id);
        }
        if(name != null && !name.isEmpty()){
            queryWrapper.like("name",name);
        }
        Page<Boardroom> boardroomPage = boardroomMapper.selectPage(page, queryWrapper);

        return boardroomPage.convert(boardroom -> {
            List<Device> devices = deviceService.findByBoardroomId(boardroom.getId());
            return new BoardroomDevVO(boardroom,devices);
        });
    }

    @Transactional
    @Override
    public ResultVO<String> addBoardroomWithDevices(BoardroomAddDTO dto) {

        QueryWrapper<Boardroom> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", dto.getName());
        if (boardroomMapper.selectCount(queryWrapper) > 0) {
           return ResultVO.fail("会议室名称已存在");
        }

        Boardroom boardroom = new Boardroom();
        boardroom.setName(dto.getName());
        boardroom.setType(dto.getType());
        boardroom.setSeats(dto.getSeats());
        boardroom.setPrice(dto.getPrice());
        boardroom.setArea(dto.getArea());
        boardroomMapper.insert(boardroom);

        if (dto.getDevices() != null) {
            for (DeviceDTO deviceDTO : dto.getDevices()) {
                Device device = new Device();
                device.setName(deviceDTO.getName());
                device.setBoardroomId(boardroom.getId());
                deviceService.save(device);
            }
        }
        return ResultVO.success("添加成功");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultVO<String> updateBoardroomWithDevices(BoardroomUpdateDTO dto) throws Exception {

        Boardroom existingBoardroom = boardroomMapper.selectById(dto.getId());
        if (existingBoardroom == null) {
            return ResultVO.fail("会议室不存在");
        }
        if (hasFutureReservations(dto.getId())) {
            return ResultVO.fail("会议室已被锁定、预订或维护，不允许修改");
        }
        QueryWrapper<Boardroom> nameQuery = new QueryWrapper<>();
        nameQuery.eq("name", dto.getName())
                .ne("id", dto.getId());
        if (boardroomMapper.selectCount(nameQuery) > 0) {
            return ResultVO.fail("会议室名称已存在");
        }
        Boardroom boardroom = new Boardroom();
        boardroom.setId(dto.getId());
        boardroom.setName(dto.getName());
        boardroom.setType(dto.getType());
        boardroom.setSeats(dto.getSeats());
        boardroom.setPrice(dto.getPrice());
        boardroom.setArea(dto.getArea());
        boardroomMapper.updateById(boardroom);
        QueryWrapper<Device> deviceQuery = new QueryWrapper<>();
        deviceQuery.eq("boardroom_id", dto.getId());
        deviceService.remove(deviceQuery);
        if (dto.getDevices() != null && !dto.getDevices().isEmpty()) {
            List<Device> devices = dto.getDevices().stream()
                    .map(deviceDTO -> {
                        Device device = new Device();
                        device.setName(deviceDTO.getName());
                        device.setBoardroomId(dto.getId());
                        return device;
                    })
                    .collect(Collectors.toList());
            deviceService.saveBatch(devices);
        }
        return ResultVO.success("修改成功");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultVO<String> deleteBoardroomWithDevices(Integer id) throws Exception {
        Boardroom boardroom = boardroomMapper.selectById(id);
        if (boardroom == null) {
            return ResultVO.fail("会议室不存在");
        }
        if (hasFutureReservations(id)) {
            return ResultVO.fail("会议室已被锁定、预订或维护，不允许删除");
        }
        QueryWrapper<Device> deviceQuery = new QueryWrapper<>();
        deviceQuery.eq("boardroom_id", id);
        deviceService.remove(deviceQuery);
        boardroomMapper.deleteById(id);

        return ResultVO.success("删除成功");
    }

    @Override
    public IPage<Boardroom> getBoardrooms(Integer page, Integer pageSize, String name, Integer type, Integer minSeats, Integer maxSeats) {
        // 创建分页对象
        Page<Boardroom> pageInfo = new Page<>(page, pageSize);

        // 创建查询条件
        LambdaQueryWrapper<Boardroom> queryWrapper = new LambdaQueryWrapper<>();

        // 添加名称条件（模糊查询）
        if (StringUtils.isNotBlank(name)) {
            queryWrapper.like(Boardroom::getName, name);
        }

        // 添加类型条件
        if (type != null) {
            queryWrapper.eq(Boardroom::getType, type);
        }

        // 添加座位数范围条件
        if (minSeats != null && maxSeats != null) {
            queryWrapper.between(Boardroom::getSeats, minSeats, maxSeats);
        } else if (minSeats != null) {
            queryWrapper.ge(Boardroom::getSeats, minSeats);
        } else if (maxSeats != null) {
            queryWrapper.le(Boardroom::getSeats, maxSeats);
        }

        // 执行分页查询
        return baseMapper.selectPage(pageInfo, queryWrapper);
    }

    //查找符合用户要求的会议室
    @Override
    public IPage<BoardroomDevVO> searchBoardrooms(String date, String startTime, String endTime, Integer attendees, List<String> devices, Integer page, Integer pageSize) {
        // 创建分页对象
        Page<BoardroomDevVO> pageObj = new Page<>(page, pageSize);

        // 构造查询条件
        QueryWrapper<Boardroom> queryWrapper = new QueryWrapper<>();

        // 查询所有会议室，用于过滤
        List<Boardroom> allBoardrooms = boardroomMapper.selectList(queryWrapper);

        // 筛选出符合条件的会议室
        List<BoardroomDevVO> filteredBoardrooms = allBoardrooms.stream()
                //时间段内空闲的会议室
                .filter(boardroom -> isAvailable(boardroom.getId(), date, startTime, endTime))
                //座位数足够
                .filter(boardroom -> boardroom.getSeats() >= attendees)
                //设备满足要求
                .filter(boardroom -> devices == null || devices.isEmpty() ||
                        deviceService.findByBoardroomId(boardroom.getId()).stream()
                                .map(Device::getName)
                                .collect(Collectors.toSet()).containsAll(devices))
                .map(boardroom -> {
                    List<Device> devicesInBoardroom = deviceService.findByBoardroomId(boardroom.getId());
                    return new BoardroomDevVO(boardroom, devicesInBoardroom);
                })
                .collect(Collectors.toList());

        // 将结果转换为分页对象
        IPage<BoardroomDevVO> resultPage = new Page<>(pageObj.getCurrent(), pageObj.getSize(), filteredBoardrooms.size());
        resultPage.setRecords(filteredBoardrooms.stream().skip((pageObj.getCurrent() - 1) * pageObj.getSize())
                .limit(pageObj.getSize()).collect(Collectors.toList()));

        // 设置正确的总记录数为过滤后的会议室数量
        resultPage.setTotal(filteredBoardrooms.size());

        return resultPage;
    }

    //判断该会议室在指定时间段内是否空闲
    private boolean isAvailable(Integer boardroomId, String dateStr, String startTimeStr, String endTimeStr) {
        // 创建一个 SimpleDateFormat 对象，用于解析日期字符串
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            // 解析日期字符串为 Date 对象
            Date date = sdf.parse(dateStr);

            // 将时间字符串转换为 Date 对象，这里假设 startTimeStr 和 endTimeStr 是 "HH:mm" 格式
            SimpleDateFormat timeSdf = new SimpleDateFormat("HH:mm");
            Date startTime = timeSdf.parse(startTimeStr);
            Date endTime = timeSdf.parse(endTimeStr);

            // 创建 QueryWrapper 对象并设置查询条件
            QueryWrapper<BoardroomState> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("boardroom_id", boardroomId)
                    .eq("date", date); // 只比较年月日
            List<BoardroomState> states = boardroomStateMapper.selectList(queryWrapper);

            if (states.isEmpty()) {
                return true; // 没有记录，代表空闲
            }

            for (BoardroomState state : states) {
                Date stateStartTime = state.getStartTime();
                Date stateEndTime = state.getEndTime();
                if (!(stateEndTime.before(startTime) || stateStartTime.after(endTime) || stateEndTime.equals(startTime) || stateStartTime.equals(endTime))) {
                    return false; // 时间不重叠，代表不空闲
                }
            }
            return true; // 所有记录的时间不重叠，空闲
        } catch (ParseException e) {
            e.printStackTrace();
            return false; // 解析错误，返回不空闲
        }
    }

    @Override
    public Integer  getBoardroomIdByName(String name) {
        LambdaQueryWrapper<Boardroom> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Boardroom::getName, name); // 指定查询条件
        Boardroom boardroom = this.getOne(queryWrapper); // 查询单个结果
        return boardroom != null ? boardroom.getId() : null;
    }

    @Override
    public List<BoardroomStatusDTO> getStatusByDate(Integer id, Date date) {
        // 1. 查询当天的所有会议室状态
        QueryWrapper<BoardroomState> stateQuery = new QueryWrapper<>();
        stateQuery.eq("boardroom_id",id);
        stateQuery.eq("date", date);
        stateQuery.orderByAsc("start_time");

        List<BoardroomState> states = boardroomStateMapper.selectList(stateQuery);

        // 2. 转换为DTO并关联预定人信息
        return states.stream().map(state -> {
            BoardroomStatusDTO dto = new BoardroomStatusDTO();
            dto.setStartTime(DateUtils.formatTime(state.getStartTime()));
            dto.setEndTime(DateUtils.formatTime(state.getEndTime()));
            dto.setState(state.getState());

            // 如果是预订或使用状态，关联预定人信息
            if (state.getState() == 3 || state.getState() == 4) {
                dto.setBooker(getBookerByStateId(state.getId()));
            }

            return dto;
        }).collect(Collectors.toList());
    }
    private String getBookerByStateId(Integer stateId) {
        // 1. 根据stateId查找关联的订单
        QueryWrapper<Orders> orderQuery = new QueryWrapper<>();
        orderQuery.eq("state_id", stateId);
        Orders order = ordersMapper.selectOne(orderQuery);

        if (order != null) {
            // 2. 根据订单中的customerId查找客户姓名
            return customerMapper.selectById(order.getCustomerId()).getName();
        }
        return null;
    }
}

